﻿using System.Collections.Generic;

namespace Red.EngineData.Protocol
{
    /// <summary>
    /// Parses path like "path.to.object[44]" to tokens.
    /// </summary>
    public static class InteropPathParser
    {
        /// <summary>
        /// Extract tokens from path.
        /// </summary>
        /// <param name="path"></param>
        /// <returns></returns>
        public static List<string> Tokenize( string path )
        {
            if ( path.Length == 0 )
                throw new InteropPathParserEmptyPathException( "Path should not be empty." );

            TextParser parser = new TextParser( path );

            string identifier;

            // Starting with identifier
            if ( parser.ParseIdentifier( out identifier ) == false )
                throw new InteropPathParserInvalidSyntaxException( "Path should start with identifier (alphanumeric string, starting with letter)." );

            List<string> tokens = new List<string>();

            tokens.Add( identifier );       // Add first identifier

            while ( parser.IsEndOfStream() == false )
            {
                bool tokenFound = false;

                // Followed by "."
                if ( parser.ParseKeyword( "." ) == false )
                {
                    if ( parser.ParseKeyword( "[" ) )
                    {
                        int index = 0;

                        if ( parser.ParseIdentifier( out identifier ) ) // Can be a number, alphanumeric starting with letter, or string
                        {
                            if ( parser.ParseKeyword( "]" ) )
                            {
                                identifier = "[" + identifier + "]";    // add brackets
                                tokenFound = true;
                            }
                        }
                        else if ( parser.ParseString( out identifier ) )
                        {
                            if ( parser.ParseKeyword( "]" ) )
                            {
                                identifier = "[\"" + identifier + "\"]";    // add quote and brackets
                                tokenFound = true;
                            }
                        }
                        else if ( parser.ParseNumber( out index ) )
                        {
                            if ( parser.ParseKeyword( "]" ) )
                            {
                                identifier = "[" + index.ToString() + "]";    // add brackets
                                tokenFound = true;
                            }
                        }
                    }
                    else
                    {
                        throw new InteropPathParserInvalidSyntaxException( "Identifier should be followed by \".\" or \"[\"." );
                    }
                }
                else
                {
                    // Followed by identifier or array index (number or identifier like [0] [something])
                    if ( parser.ParseIdentifier( out identifier ) )
                    {
                        tokenFound = true;
                    }
                }

                // Add token to list if everything is correct
                if ( tokenFound )
                    tokens.Add( identifier );
                else
                    throw new InteropPathParserInvalidSyntaxException( "Token should be an alphanumeric identifier starting with letter or an array index like [n]." );
            }

            return tokens;
        }
    }
}
